Micron Document
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
| SparkN0de-git | SparkN0de |
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------


Displaying Raw • Download


vendor/lxmfy/tests/test_chaos.py dev (c9f60cc5) Text, 4.74 KB

T8b949e"""Chaos and fault injection testing for off-grid reliability."""

Tff7b72import T7ee787random
Tff7b72import T7ee787time
Tff7b72import T7ee787pytest
Tff7b72from T7ee787unittestT7ee787.T7ee787mock Tff7b72import Te6edf3MagicMockTb4b4b4, Te6edf3patch
Tff7b72from T7ee787lxmfy Tff7b72import Te6edf3BotConfigTb4b4b4, Te6edf3LXMFBot
Tff7b72from T7ee787lxmfyT7ee787.T7ee787storage Tff7b72import Te6edf3StorageTb4b4b4, Te6edf3JSONStorage


Tff7b72class T56d364FailingStorageBackendTb4b4b4:
T8b949e"""A storage backend that periodically fails or corrupts data."""

Tff7b72def Tff7b72__init__Tb4b4b4(Tff7b72selfTb4b4b4, Te6edf3real_backendTb4b4b4, Te6edf3failure_rateTff7b72=T79c0ff0.1Tb4b4b4)Tb4b4b4:
Tff7b72selfTff7b72.Td2a8ffreal Tff7b72= Te6edf3real_backend
Tff7b72selfTff7b72.Td2a8fffailure_rate Tff7b72= Te6edf3failure_rate

Tff7b72def Td2a8ffsetTb4b4b4(Tff7b72selfTb4b4b4, Te6edf3keyTb4b4b4, Te6edf3valueTb4b4b4)Tb4b4b4:
Tff7b72if Te6edf3randomTff7b72.Td2a8ffrandomTb4b4b4(Tb4b4b4) Tff7b72< Tff7b72selfTff7b72.Td2a8fffailure_rateTb4b4b4:
T8b949e# Simulate a "Partial Write" by corrupting the value
Tff7b72if Tffa657isinstanceTb4b4b4(Te6edf3valueTb4b4b4, Tffa657strTb4b4b4)Tb4b4b4:
Te6edf3value Tff7b72= Te6edf3valueTb4b4b4[Tb4b4b4: Tffa657lenTb4b4b4(Te6edf3valueTb4b4b4) Tff7b72/Tff7b72/ T79c0ff2Tb4b4b4] Tff7b72+ Ta5d6ff"Ta5d6ff [CORRUPTED] Ta5d6ff"
Tff7b72elif Tffa657isinstanceTb4b4b4(Te6edf3valueTb4b4b4, Tffa657dictTb4b4b4)Tb4b4b4:
Te6edf3valueTb4b4b4[Ta5d6ff"Ta5d6ffcorruptTa5d6ff"Tb4b4b4] Tff7b72= Tff7b72True
Tff7b72return Tff7b72selfTff7b72.Td2a8ffrealTff7b72.Td2a8ffsetTb4b4b4(Te6edf3keyTb4b4b4, Te6edf3valueTb4b4b4)

Tff7b72def Td2a8ffgetTb4b4b4(Tff7b72selfTb4b4b4, Te6edf3keyTb4b4b4, Te6edf3defaultTff7b72=Tff7b72NoneTb4b4b4)Tb4b4b4:
Tff7b72if Te6edf3randomTff7b72.Td2a8ffrandomTb4b4b4(Tb4b4b4) Tff7b72< Tff7b72selfTff7b72.Td2a8fffailure_rateTb4b4b4:
Tff7b72raise Tf85149OSErrorTb4b4b4(Ta5d6ff"Ta5d6ffI/O Error: SD Card Read Failed (Simulated)Ta5d6ff"Tb4b4b4)
Tff7b72return Tff7b72selfTff7b72.Td2a8ffrealTff7b72.Td2a8ffgetTb4b4b4(Te6edf3keyTb4b4b4, Te6edf3defaultTb4b4b4)

Tff7b72def Td2a8ffdeleteTb4b4b4(Tff7b72selfTb4b4b4, Te6edf3keyTb4b4b4)Tb4b4b4:
Tff7b72return Tff7b72selfTff7b72.Td2a8ffrealTff7b72.Td2a8ffdeleteTb4b4b4(Te6edf3keyTb4b4b4)

Tff7b72def Td2a8ffexistsTb4b4b4(Tff7b72selfTb4b4b4, Te6edf3keyTb4b4b4)Tb4b4b4:
Tff7b72return Tff7b72selfTff7b72.Td2a8ffrealTff7b72.Td2a8ffexistsTb4b4b4(Te6edf3keyTb4b4b4)

Tff7b72def Td2a8ffscanTb4b4b4(Tff7b72selfTb4b4b4, Te6edf3prefixTb4b4b4)Tb4b4b4:
Tff7b72return Tff7b72selfTff7b72.Td2a8ffrealTff7b72.Td2a8ffscanTb4b4b4(Te6edf3prefixTb4b4b4)


Tf0883e@pytestTff7b72.Td2a8ffmarkTff7b72.Td2a8ffreliability
Tff7b72class T56d364TestChaosBotTb4b4b4:
T8b949e"""Stress testing the bot under simulated hardware/protocol failures."""

Tff7b72def Td2a8fftest_time_drift_resilienceTb4b4b4(Tff7b72selfTb4b4b4, Te6edf3test_config_dirTb4b4b4)Tb4b4b4:
T8b949e"""Verify that the bot handles large system clock jumps."""
Te6edf3config Tff7b72= Te6edf3BotConfigTb4b4b4(
Te6edf3nameTff7b72=Ta5d6ff"Ta5d6ffTimeDriftBotTa5d6ff"Tb4b4b4,
Te6edf3storage_pathTff7b72=Tffa657strTb4b4b4(Te6edf3test_config_dir Tff7b72/ Ta5d6ff"Ta5d6fftime_driftTa5d6ff"Tb4b4b4)Tb4b4b4,
Te6edf3test_modeTff7b72=Tff7b72TrueTb4b4b4,
Tb4b4b4)
Te6edf3bot Tff7b72= Te6edf3LXMFBotTb4b4b4(Tff7b72*Tff7b72*Te6edf3configTff7b72.Td2a8ff__dict__Tb4b4b4)

T8b949e# Mocking time.time
Te6edf3start_time Tff7b72= T79c0ff1700000000.0

Tff7b72with Te6edf3patchTb4b4b4(Ta5d6ff"Ta5d6fftime.timeTa5d6ff"Tb4b4b4, Te6edf3return_valueTff7b72=Te6edf3start_timeTb4b4b4)Tb4b4b4:
T8b949e# Record some activity
Te6edf3botTff7b72.Td2a8ffstorageTff7b72.Td2a8ffsetTb4b4b4(Ta5d6ff"Ta5d6fflast_seenTa5d6ff"Tb4b4b4, Te6edf3timeTff7b72.Td2a8fftimeTb4b4b4(Tb4b4b4)Tb4b4b4)

T8b949e# Jump forward 1 year
Te6edf3future_time Tff7b72= Te6edf3start_time Tff7b72+ Tb4b4b4(T79c0ff365 Tff7b72* T79c0ff24 Tff7b72* T79c0ff3600Tb4b4b4)
Tff7b72with Te6edf3patchTb4b4b4(Ta5d6ff"Ta5d6fftime.timeTa5d6ff"Tb4b4b4, Te6edf3return_valueTff7b72=Te6edf3future_timeTb4b4b4)Tb4b4b4:
T8b949e# Bot should still function
Te6edf3botTff7b72.Td2a8ffstorageTff7b72.Td2a8ffsetTb4b4b4(Ta5d6ff"Ta5d6ffcurrent_eventTa5d6ff"Tb4b4b4, Ta5d6ff"Ta5d6ffChecking after driftTa5d6ff"Tb4b4b4)
Te6edf3last_seen Tff7b72= Te6edf3botTff7b72.Td2a8ffstorageTff7b72.Td2a8ffgetTb4b4b4(Ta5d6ff"Ta5d6fflast_seenTa5d6ff"Tb4b4b4)
Tff7b72assert Te6edf3last_seen Tff7b72== Te6edf3start_time

T8b949e# Jump backward 1 year (RTC battery failure)
Te6edf3past_time Tff7b72= Te6edf3start_time Tff7b72- Tb4b4b4(T79c0ff365 Tff7b72* T79c0ff24 Tff7b72* T79c0ff3600Tb4b4b4)
Tff7b72with Te6edf3patchTb4b4b4(Ta5d6ff"Ta5d6fftime.timeTa5d6ff"Tb4b4b4, Te6edf3return_valueTff7b72=Te6edf3past_timeTb4b4b4)Tb4b4b4:
Te6edf3botTff7b72.Td2a8ffstorageTff7b72.Td2a8ffsetTb4b4b4(Ta5d6ff"Ta5d6ffpanic_eventTa5d6ff"Tb4b4b4, Ta5d6ff"Ta5d6ffClock rolled backTa5d6ff"Tb4b4b4)
Tff7b72assert Te6edf3botTff7b72.Td2a8ffstorageTff7b72.Td2a8ffgetTb4b4b4(Ta5d6ff"Ta5d6ffpanic_eventTa5d6ff"Tb4b4b4) Tff7b72== Ta5d6ff"Ta5d6ffClock rolled backTa5d6ff"

Tff7b72def Td2a8fftest_storage_fault_injectionTb4b4b4(Tff7b72selfTb4b4b4, Te6edf3test_config_dirTb4b4b4)Tb4b4b4:
T8b949e"""Verify the bot can survive intermittent storage failures."""
Te6edf3json_backend Tff7b72= Te6edf3JSONStorageTb4b4b4(Tffa657strTb4b4b4(Te6edf3test_config_dir Tff7b72/ Ta5d6ff"Ta5d6ffchaos_jsonTa5d6ff"Tb4b4b4)Tb4b4b4)
Te6edf3chaos_backend Tff7b72= Te6edf3FailingStorageBackendTb4b4b4(Te6edf3json_backendTb4b4b4, Te6edf3failure_rateTff7b72=T79c0ff0.2Tb4b4b4)
Te6edf3storage Tff7b72= Te6edf3StorageTb4b4b4(Te6edf3chaos_backendTb4b4b4)

Te6edf3success_count Tff7b72= T79c0ff0
Te6edf3error_count Tff7b72= T79c0ff0

Tff7b72for Te6edf3i Tff7b72in Tffa657rangeTb4b4b4(T79c0ff100Tb4b4b4)Tb4b4b4:
Tff7b72tryTb4b4b4:
Te6edf3storageTff7b72.Td2a8ffsetTb4b4b4(Ta5d6fffTa5d6ff"Ta5d6ffkey_Tffd700{Te6edf3iTffd700}Ta5d6ff"Tb4b4b4, Tb4b4b4{Ta5d6ff"Ta5d6ffdataTa5d6ff"Tb4b4b4: Ta5d6ff"Ta5d6ffimportant infoTa5d6ff"Tb4b4b4}Tb4b4b4)
Te6edf3val Tff7b72= Te6edf3storageTff7b72.Td2a8ffgetTb4b4b4(Ta5d6fffTa5d6ff"Ta5d6ffkey_Tffd700{Te6edf3iTffd700}Ta5d6ff"Tb4b4b4)
Tff7b72if Te6edf3valTb4b4b4:
Te6edf3success_count Tff7b72+Tff7b72= T79c0ff1
Tff7b72except Tf85149ExceptionTb4b4b4:
Te6edf3error_count Tff7b72+Tff7b72= T79c0ff1

Tffa657printTb4b4b4(
Ta5d6fffTa5d6ff"Tffea00\nTa5d6ff[Chaos Storage] Successes: Tffd700{Te6edf3success_countTffd700}Ta5d6ff, Simulated Errors: Tffd700{Te6edf3error_countTffd700}Ta5d6ff"
Tb4b4b4)
T8b949e# The goal is not 100% success, but that the framework doesn't CRASH the entire process
Tff7b72assert Tb4b4b4(Te6edf3success_count Tff7b72+ Te6edf3error_countTb4b4b4) Tff7b72== T79c0ff100

Tff7b72def Td2a8fftest_message_storm_deduplicationTb4b4b4(Tff7b72selfTb4b4b4, Te6edf3test_config_dirTb4b4b4)Tb4b4b4:
T8b949e"""Test the bot's ability to handle massive duplicate message storms."""
Te6edf3config Tff7b72= Te6edf3BotConfigTb4b4b4(
Te6edf3nameTff7b72=Ta5d6ff"Ta5d6ffStormBotTa5d6ff"Tb4b4b4,
Te6edf3storage_pathTff7b72=Tffa657strTb4b4b4(Te6edf3test_config_dir Tff7b72/ Ta5d6ff"Ta5d6ffstorm_storageTa5d6ff"Tb4b4b4)Tb4b4b4,
Te6edf3test_modeTff7b72=Tff7b72TrueTb4b4b4,
Te6edf3first_message_enabledTff7b72=Tff7b72FalseTb4b4b4,
Tb4b4b4)
Te6edf3bot Tff7b72= Te6edf3LXMFBotTb4b4b4(Tff7b72*Tff7b72*Te6edf3configTff7b72.Td2a8ff__dict__Tb4b4b4)

Te6edf3processed_count Tff7b72= T79c0ff0

Tff7b72def Td2a8ffhandlerTb4b4b4(Te6edf3senderTb4b4b4, Te6edf3msgTb4b4b4)Tb4b4b4:
Tff7b72nonlocal Te6edf3processed_count
Te6edf3processed_count Tff7b72+Tff7b72= T79c0ff1
Tff7b72return Tff7b72True

Te6edf3botTff7b72.Td2a8ffmessage_handlersTff7b72.Td2a8ffappendTb4b4b4(Te6edf3handlerTb4b4b4)

T8b949e# Create a mock message
Tff7b72import T7ee787LXMF

Te6edf3mock_msg Tff7b72= Te6edf3MagicMockTb4b4b4(Te6edf3specTff7b72=Te6edf3LXMFTff7b72.Td2a8ffLXMessageTb4b4b4)
Te6edf3mock_msgTff7b72.Td2a8ffcontent Tff7b72= Ta5d6ffbTa5d6ff"Ta5d6ffSingle messageTa5d6ff"
Te6edf3mock_msgTff7b72.Td2a8ffhash Tff7b72= Ta5d6ffbTa5d6ff"Ta5d6ffunique_hash_123Ta5d6ff"
Te6edf3mock_msgTff7b72.Td2a8ffsource_hash Tff7b72= Ta5d6ffbTa5d6ff"Ta5d6ffsenderTa5d6ff"
Te6edf3mock_msgTff7b72.Td2a8ffdestination_hash Tff7b72= Ta5d6ffbTa5d6ff"Ta5d6fflocalTa5d6ff"
Te6edf3mock_msgTff7b72.Td2a8fffields Tff7b72= Tb4b4b4{Tb4b4b4}
Te6edf3mock_msgTff7b72.Td2a8ffsignature_validated Tff7b72= Tff7b72True

T8b949e# Send the EXACT SAME message 50 times
Tff7b72with Te6edf3patchTb4b4b4(Ta5d6ff"Ta5d6fflxmfy.core.verify_incoming_messageTa5d6ff"Tb4b4b4, Te6edf3return_valueTff7b72=Tff7b72TrueTb4b4b4)Tb4b4b4:
Tff7b72for Te6edf3_ Tff7b72in Tffa657rangeTb4b4b4(T79c0ff50Tb4b4b4)Tb4b4b4:
Te6edf3botTff7b72.Td2a8ff_message_receivedTb4b4b4(Te6edf3mock_msgTb4b4b4)

T8b949e# Should only have been processed ONCE due to deduplication receipts
Tff7b72assert Te6edf3processed_count Tff7b72== T79c0ff1


──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────